/*************************************
Copyright 2011 Chinua Iloabachie, Pradnya Khutafale, Siyi Liu, Junichi Suzuki, and The University of Massachusetts, Boston (http://code.google.com/p/tabletuml/)


Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 
*************************************/



package touchMe.baseClass;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import android.util.Log;

import touchMe.Util.XMLContentHandler;
import touchMe.baseClass.Diagram;



public class DiagramFileHandler {
	/** Create an xml version of a Diagram object by calling
	 * createStringToBeSaved() and write2File()
	 * @param fileName - name of file to be written
	 * @param diagram - Diagram object
	 * @return boolean - true if successful, false otherwise
	 */
	public static boolean writeDiagram(String fileName,Diagram diagram){
		try{
			 
			boolean fileExists=write2File(fileName,createStringToBeSaved(diagram));
            return fileExists; 
			 
		}catch(Exception e){
			Log.d(Constants.TAG,e.getMessage());
			return false;}
		
	}
	/** Create an xml version of a Diagram object
	 * @param diagram - Diagram object
	 * @return xml string
	 */
	public static String createStringToBeSaved(Diagram diagram) {
		DocumentBuilder db = null;
		try {
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			db = dbf.newDocumentBuilder();
		} catch (Exception e) {
			System.out.println("Error saving XML."+e.getLocalizedMessage());
		}
		Document doc = db.newDocument();

		Element root = doc.createElement("umlet_diagram");
		doc.appendChild(root);

		// save helptext
		Element help = doc.createElement("help_text");
		if(diagram.getHelpText()!=null)
		help.appendChild(doc.createTextNode(diagram.getHelpText()));
		else
			help.appendChild(doc.createTextNode(" "));	
		root.appendChild(help);

		// save zoom
		Element zoom = doc.createElement("zoom_level");
		zoom.appendChild(doc.createTextNode(String.valueOf(diagram.getZoomLevel())));
		root.appendChild(zoom);

		// save elements (group = null = rootlayer)
		generateElementTree(doc, diagram.getElements(), root);

		// output the stuff...
		StringWriter stringWriter = null;
		try {
			DOMSource source = new DOMSource(doc);
			stringWriter = new StringWriter();
			StreamResult result = new StreamResult(stringWriter);

			TransformerFactory transFactory = TransformerFactory.newInstance();
			Transformer transformer = transFactory.newTransformer();

			transformer.transform(source, result);
			System.out.println("source: "+source.toString()+"\n result: "+result.toString());
			
		} catch (Exception e) {
			System.out.println("Error saving XML."+ e.getLocalizedMessage());
		}
		//System.out.println("OUT: "+stringWriter.toString());
		return stringWriter.toString();

	}
  
	  /** Generates the inner elements in the document tree, adapted from umLet
	 * @param doc - document tree
	 * @param entities - elements of the tree
	 * @param current - start node usually the root
	 */
	private static void generateElementTree(Document doc, List<touchMe.baseClass.Element> entities, Element current) {
	  final String  classType="com.umlet.element.base.Class";
	  final String  actorType="com.umlet.element.base.Actor";
	  final String  relationType="com.umlet.element.base.Relation";
	  for (touchMe.baseClass.Element e : entities) {
			Element el = doc.createElement("element");
			current.appendChild(el);

			Element elType = doc.createElement("type");
			
			if(e.getType().toString().equals("CLASS"))
				elType.appendChild(doc.createTextNode(classType));
			else if(e.getType().toString().equals("ACTOR"))
				elType.appendChild(doc.createTextNode(actorType));
			else if(e.getType().toString().equals("RELATION"))
				elType.appendChild(doc.createTextNode(relationType));
			
			el.appendChild(elType);

			Element elCoor = doc.createElement("coordinates");
			el.appendChild(elCoor);

			Element elX = doc.createElement("x");
			elX.appendChild(doc.createTextNode("" + (int)e.getX()));
			elCoor.appendChild(elX);

			Element elY = doc.createElement("y");
			elY.appendChild(doc.createTextNode("" + (int)e.getY()));
			elCoor.appendChild(elY);

			Element elW = doc.createElement("w");
			elW.appendChild(doc.createTextNode("" + (int)e.getW()));
			elCoor.appendChild(elW);

			Element elH = doc.createElement("h");
			elH.appendChild(doc.createTextNode("" + (int)e.getH()));
			elCoor.appendChild(elH);

			Element elPA = doc.createElement("panel_attributes");
			elPA.appendChild(doc.createTextNode(e.getPanelAttributes().toString()));
			el.appendChild(elPA);
			
			
			
			
		}
			
	}
  
   /** Writes content to a file named fileName
	 * @param fileName - name of file to be written
	 * @param content - content of file
	 */
	public static boolean write2File(String fileName,String content){
		try{
		File outFile=new File(fileName);
		
		  if(outFile.exists()&& Constants.explorerMode==Constants.SAVEAS)
		    return false;
  	    FileOutputStream outStream=new FileOutputStream(outFile);
  	    OutputStreamWriter out = new OutputStreamWriter(outStream);
	        out.write(content);
	        out.close();
		  
	  }catch(Exception e){
		  e.printStackTrace();
	  }finally{}
	  
	  return true;
	  }
	
	public void doOpen() {
		try {
			try {
				SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
				FileInputStream input = new FileInputStream(new File("class.xml"));
				XMLContentHandler xmlhandler = new XMLContentHandler();
				parser.parse(input, xmlhandler);
			} catch (SAXException e) {
				//log.error("Error parsing the inputstream.", e);
			}
			/*
			 * } catch (IOException e) {
			 * log.error(null, e);
			 */
		} catch (Exception e) {
			//log.error(null, e);

		}
	}

}
